from typing import Any
from nicegui import ui,APIRouter,run,app
import shelve
from config import database_path
from public import textfsm_run
import pandas as pd
import webview



class DATA:
    def __init__(self,datas:list[dict],key) -> None:
        self.datas=datas
        self.key=key
    def result(self):
        return self.datas
    def delete(self, key):
        for index , data in  enumerate (self.datas):
            if data[self.key]==key:
                self.datas.remove(data)
                return self.datas
    
    def update(self,newdata:dict):
        key=newdata.get(self.key,None)
        if key:
            for index, data in  enumerate (self.datas):
                if data[self.key]==key:
                    self.datas[index]=newdata
                    return self.datas
            # 新的数据
            self.datas.append(newdata)
            return self.datas
            
        else:
            return Exception('key is not exist')
        
    def add(self,newdata:dict):
        key=newdata.get(self.key,None)
        if key:
            for index, data in  enumerate (self.datas):
                if data[self.key]==key:
                    self.datas[index]=newdata
                    return self.datas
            # 新的数据
            self.datas.append(newdata)
            return self.datas
        else:
            return Exception('key is not exist')
        
        
        self.datas.append(newdata)
        return self.datas
    
    def find_keys(self):
        keys=[]
        for index, data in  enumerate (self.datas):
            keys.append(data[self.key])
        return list(set(keys))
    def find(self,key):
        for index, data in  enumerate (self.datas):
            if data[self.key]==key:
                return data
    


# public_view 数据类型
[
    {
        "设备类型": "hW",
        "设备名称分割符": "121",
        "获取设备名称textfsm": "$&{hauwei}",
        "描述": 'null',
        "id": 1
    },
    {
        "设备类型": "hW",
        "设备名称分割符": "121",
        "获取设备名称textfsm": "$&{hauwei}",
        "描述": 'null',
        "id": 2
    }
]

# public_view 配置视图
class display_public_config():
    def __init__(self) -> None:
        with shelve.open(database_path) as self.db:
            rows=self.db['public_datas']

        columns = [{'name': '设备类型','label': '设备类型', 'field': '设备类型', 'resizable': True,'align': 'left','sortable': True,},
                   {'name': '设备名称分割符','label': '设备名称分割符','field': '设备名称分割符', 'resizable': True, 'align': 'left','sortable': True,},
                   {'name': '获取设备名称textfsm','label': '获取设备名称textfsm', 'field': '获取设备名称textfsm', 'resizable': True, 'align': 'left','sortable': True,},
                   {'name': '描述','label': '描述','field': '描述', 'resizable': True, 'align': 'left','sortable': True,},]
        self.table=ui.table(columns=columns, rows=rows, pagination=5)

        self.table.style('height: 100%;  width: 100%;')
        self.table.props('title="公共配置表" auto-width  ')
        self.table.on('rowDblclick', self.onRowDblclick) 

    
    def onRowDblclick(self,evt):
        datas=evt.args[1]
        crud_public_db(args=datas,update_ui=self) 
    
    def update(self):
        print('更新数据')
        with shelve.open(database_path) as self.db:
            rows=self.db['public_datas']
        self.table.rows=rows
        self.table.update()


class crud_public_db():
    def __init__(self,args:dict={},update_ui=None) -> None:
        # print('crud_public_db 的默认值' ,args)
        self.args=args  
        self.update_ui=update_ui
        with ui.dialog(value=True).classes('w-full flex-nowrap') as self.dialog, ui.card().classes('w-full flex-nowrap'):
            with ui.input('设备类型',value=args.get('设备类型','')).classes('w-full flex-nowrap') as self.device_type:
                ui.tooltip('提示说明')
                
            with ui.input('设备名称分割符',value=args.get('设备名称分割符','')).classes('w-full flex-nowrap') as self.device_name_split :
                ui.tooltip('提示说明')
                
            with ui.input('获取设备名称textfsm',value=args.get('获取设备名称textfsm','')).classes('w-full flex-nowrap').props('  type="textarea"  outlined    clearable') as self.gte_device_name_textfsm:
                ui.tooltip('提示说明')
                
            with ui.input('描述',value=args.get('描述','')).classes('w-full flex-nowrap').props('  type="textarea"  outlined    clearable') as self.description:
                ui.tooltip('提示说明')
                
            with ui.row():
                ui.button("关闭", on_click=lambda: self.dialog.close())
                ui.button("增加",on_click=self.add_config)
                ui.button("删除",on_click=self.del_config)
                ui.button("修改",on_click=self.update_config)
    def add_config(self):
        # print("add_config")
        with shelve.open(database_path) as db:
            public_datas=DATA(datas=db['public_datas'],key='设备类型')
            data={
                '设备类型':self.device_type.value,
                '设备名称分割符':self.device_name_split.value,
                '获取设备名称textfsm':self.gte_device_name_textfsm.value,
                '描述':self.description.value,
            }
            db['public_datas']=public_datas.add(data)
        self.dialog.close()
        self.update_ui.update()
        # print('增加')
    def del_config(self):
        # print('删除')
        with shelve.open(database_path) as db:
            public_datas=DATA(datas=db['public_datas'],key='设备类型')
            key=self.args.get('设备类型',None)
            # print('删除的ID',id ,self.args)
            if   key:
                public_datas.delete(key)
            
            db['public_datas']=public_datas.result()
        self.dialog.close()
        self.update_ui.update()
    
    def update_config(self):
        # print('修改')
        with shelve.open(database_path) as db:
            public_datas=DATA(datas=db['public_datas'],key='设备类型')
            key=self.args.get('设备类型',None)
            if   key:
                data={
                    '设备类型':self.device_type.value,
                    '设备名称分割符':self.device_name_split.value,
                    '获取设备名称textfsm':self.gte_device_name_textfsm.value,
                    '描述':self.description.value,
                }
                public_datas.update(data)
                db['public_datas']=public_datas.result()
        self.dialog.close()
        self.update_ui.update()


def add_public_config(public_config:display_public_config):
      crud_public_db(update_ui=public_config) 
 
 
def public_view():
    public_config=display_public_config()
    ui.button('新增',on_click=lambda:add_public_config(public_config))



#### 运行配置
# 配置数据库

class display_run_config():
    def __init__(self) -> None:
        self.on_select=None
        with shelve.open(database_path) as self.db:
            rows=self.db['run_datas']
        columns = [{'name': '表格名称','label': '表格名称', 'field': '表格名称', 'resizable': True, 'align': 'left', 'sortable': True, },
               {'name': '设备类型','label': '设备类型', 'field': '设备类型', 'resizable': True,'align': 'left','sortable': True,},
               {'name': '输入路径','label': '输入路径', 'field': '输入路径', 'resizable': True, 'align': 'left','sortable': True,},
               {'name': '文件类型','label': '文件类型','field': '文件类型', 'resizable': True, 'align': 'left','sortable': True,},
               {'name': '采集命令','label': '采集命令','field': '采集命令', 'resizable': True, 'align': 'left','sortable': True,},
               {'name': '解析模板','label': '解析模板','field': '解析模板', 'resizable': True, 'align': 'left','sortable': True,}]
        with shelve.open(database_path) as db:
            # run_datas=DATA(datas=db['run_datas'],key='表格名称')
            rows=db['run_datas']
        self.table=ui.table(columns=columns, row_key='表格名称',rows=rows,selection='multiple',on_select=lambda e: self.on_selects(e),pagination=5)
        self.table.style('height: 100%;  width: 100%;')
        self.table.props('title="运行配置" auto-width row-key="表格名称"  v-model:pagination="pagination" :loading="loading"  :filter="filter"   @request="onRequest"   binary-state-sort ') # selection="single"   v-model:selected="selected" 
        self.table.on('rowDblclick', self.onRowDblclick) 
        
        with self.table.add_slot('top-right') :
            userinput=ui.input(placeholder='搜索')
            userinput.props('clearable')
            ui.button('搜索',on_click=lambda:self.filter(userinput.value))
            
    def filter(self,value):
        table_rows=[]
        with shelve.open(database_path) as self.db:
            rows=self.db['run_datas']
        
        if value:
            for row in rows:
                if value.lower() in row['表格名称'].lower():
                    table_rows.append(row)
            self.table.rows=table_rows
            self.table.update()
        else:
            self.table.rows=rows
            self.table.update()
            
            
        
        
        
                   
        
    def on_selects(self,e):
        # print(e)
        self.on_select=e.selection
    def onRowDblclick(self,evt):
        datas=evt.args[1]
        crud_run_config(datas,update_ui=self)
        # print(datas)


    def update(self):
        print('更新数据-run_datas')
        with shelve.open(database_path) as self.db:
            rows=self.db['run_datas']
        
        self.table.rows=rows
        self.table.update()
    


class crud_run_config:
    def __init__(self,args:dict={},update_ui=None,) -> None:
        self.update_ui=update_ui
        self.args=args
        with shelve.open(database_path) as db:
            public_datas=DATA(datas=db['public_datas'],key='设备类型')
            device_types=public_datas.find_keys()
            
        with ui.dialog(value=True) as self.dialog, ui.card().classes("w-full flex-nowrap"):
            with ui.input("表格名称",value=args.get('表格名称','')).classes( "w-full flex-nowrap").props() as self.tablename:
                ui.tooltip("设备类型")

            with ui.select(device_types,label="设备类型",value=args.get('设备类型','华为',)).classes("w-full flex-nowrap") as self.device_type:
                ui.tooltip("设备类型")

            with ui.input("输入路径",value=args.get('输入路径','')).classes("w-full flex-nowrap").props() as self.inputpath:
                ui.tooltip("输入路径")

            with ui.input("文件类型", value=args.get('文件类型',"*.txt;*.log")).classes("w-full flex-nowrap" ).props() as self.filetype:
                ui.tooltip("文件类型")

            with ui.input("采集命令",value=args.get('采集命令','all')).classes("w-full flex-nowrap").props() as self.cli_command:
                ui.tooltip("采集命令")

            with ui.input("解析模板",value=args.get('解析模板','')).classes("w-full flex-nowrap").props('  type="textarea"  outlined    clearable') as self.tesfsm_file:
                ui.tooltip("解析模板")
            with ui.row():
                ui.button("关闭", on_click=lambda: self.dialog.close())
                ui.button("增加",on_click=self.add_run_config)
                ui.button("删除",on_click=self.del_run_config)
                ui.button("修改",on_click=self.update_run_config)

    def add_run_config(self):
        data={
        "表格名称": self.tablename.value,
        "设备类型": self.device_type.value,
        "输入路径": self.inputpath.value,
        "文件类型": self.filetype.value,
        "采集命令": self.cli_command.value,
        "解析模板": self.tesfsm_file.value,}
        with shelve.open(database_path) as db:
            run_datas=DATA(datas=db['run_datas'],key='表格名称')
            
            run_datas.add(data)
            
            db['run_datas']=run_datas.result()
        self.dialog.close()
        self.update_ui.update()

    def update_run_config(self):
        data={
        "表格名称": self.tablename.value,
        "设备类型": self.device_type.value,
        "输入路径": self.inputpath.value,
        "文件类型": self.filetype.value,
        "采集命令": self.cli_command.value,
        "解析模板": self.tesfsm_file.value,}
        # print('update_run_config',data)
        with shelve.open(database_path) as db:
            run_datas=DATA(datas=db['run_datas'],key='表格名称')
            
            run_datas.update(data)
            
            db['run_datas']=run_datas.result()
        self.dialog.close()
        self.update_ui.update()

    def del_run_config(self):
        with shelve.open(database_path) as db:
            run_datas=DATA(datas=db['run_datas'],key='表格名称')
            
            run_datas.delete(self.tablename.value)
            
            db['run_datas']=run_datas.result()
        self.dialog.close()
        self.update_ui.update()

def add_run_config(run_config:display_run_config):
      crud_run_config(update_ui=run_config) 

class output_selected_row:
    def __init__(self,grid) -> None:
        self.grid=grid
    

    async def output_selected_rows(self,runconfigs:list[dict],button:ui.button):
        
        ## 获取全部的配置
        run_confs=[]
        with shelve.open(database_path) as db:
            public_datas=DATA(datas=db['public_datas'],key='设备类型')
        
        for runconfig  in runconfigs:
            public=public_datas.find(runconfig['设备类型'])
            runconfig.update(public)
            run_confs.append(runconfig)
            
        # 运行配置
        # print(run_confs)
        if run_confs:
            notification = ui.notification(message='开始任务!!!',position='top',color='blue',spinner=True,timeout=60*60*2)
            # notify=ongoing_notify("开始任务!", position="top")
            try:
                # notification.type='ongoing'
                button.disable()
                # self.data ={'华为设备核对snetconf': {'result': [111], 'status': True, 'error': ''}, }
                self.data= await run.cpu_bound(textfsm_run.run_joblib,run_confs)
                self.show_Analysis_results()
            except:
                # notify.udpate_notify("任务失败!!!", type='warning')
                
                notification.message='任务失败!!!'
                notification.color="red"
                notification.spinner=False
                notification.close_button=True
            else:
                # notify.udpate_notify("任务完成!", type="info")
                notification._props['options']['timeout']=5*1000
                notification.spinner =False
                notification.type='info'
                notification.message='任务完成!!!'
                notification.color="green"
                notification.close_button=True
            finally:
                button.enable()
            
            
            # 
            
            
    
    def show_Analysis_results(self):
        # self.data ={'华为设备核对snetconf': {'result': [111], 'status': True, 'error': ''}, }
        self.grid.clear()
        with self.grid:
            self.results_df={}
            
            with  ui.dialog() as dialog, ui.card().classes("w-full flex-nowrap"):
                grid=ui.grid(columns=1)

            
            for tablename  in self.data:
                testfsm_return=self.data[tablename]['result']
                testfsm_status=self.data[tablename]['status']
                testfsm_error=self.data[tablename]['error']
                # print(testfsm_return)
                if testfsm_status:
                    with ui.expansion(tablename, icon='menu').classes('w-full'):
                        df = pd.DataFrame(testfsm_return)
                        # print(df)
                        columnDefs =[{'headerName': columns, 'field': columns,'resizable': True,'filter': 'agTextColumnFilter', 'floatingFilter': True} for columns in   df.columns.values]
                        aggrid = ui.aggrid({'columnDefs': columnDefs,'rowData': testfsm_return})

                        self.results_df.update({tablename:df}) 
                else :
                    with  grid:
                        if dialog.value:
                            pass
                        else:
                            dialog.value=True
                        ui.label(tablename).classes('text-2xl text-red')
                        ui.label(testfsm_error).classes('decoration-solid')
    async def download_result(self):
        file = await app.native.main_window.create_file_dialog(
        webview.SAVE_DIALOG, save_filename="result",file_types=("excel文件 (*.xlsx;*.xls)",))

        if file is not None:
            with pd.ExcelWriter(file) as writer:
                for  tablename  in  self.results_df:
                    df = self.results_df[tablename]
                    df.to_excel(writer, sheet_name=tablename, index=False)
            ui.notify(f"导出成功!!",position='top',color='green')

        

    
        
    






def run_view():
    run_config=display_run_config()
    
    with ui.row():
        ui.button('新增表格',on_click=lambda:add_run_config(run_config))
        run_button=ui.button('运行数据',on_click=lambda:output_selected.output_selected_rows(run_config.on_select,run_button))
        ui.button("下载数据", on_click=lambda: output_selected.download_result())
    run_config_table=ui.grid(columns=1).classes('w-full')
    output_selected =output_selected_row(run_config_table)


def page():
    with ui.expansion('公共配置(点击展开)', icon='menu').classes('w-full'):
        public_view()
    with ui.expansion('帮助文档(点击展开)', icon='menu').classes('w-full'):
        with ui.row():
            ui.link('TextFSM 文档',new_tab=True,target='https://blog.csdn.net/qq_42077348/article/details/134349219').classes('text-2xl')
            ui.link('工具文档案例',new_tab=True,target='https://blog.csdn.net/qq_42077348/category_12544079.html').classes('text-2xl')
    ui.separator()
    run_view()